// const _ = require('lodash');

const { reject } = require("lodash");

// lodash 中函数组合方法之 flowright（）
const PENDING ="pending"; //等待状态
const FULFILLED = "fulfilled"; // 成功状态
const REJECTED = "rejected"; //失败状态

class MyPromise{
  constructor (executor) {
    try{;
      executor(this.resolve,this.reject);
    }catch(e){
      this.reject(e)
    }
  }
  // promist状态
  status=PENDING;
  // success
  value=undefined;
  // fulfill
  reason=undefined;
  // 成功回调
  successCallback=[];
  // 失败回调
  failCallback=[];
  resolve=value=>{
    // 判断状态不为等待，阻止执行
    if(this.status !== PENDING) return;
    // 更改状态为成功
    this.status=FULFILLED;
    // 保存成功的值
    this.value=value;
    // 判断成功回调是否存在，存在=>调用
    // this.successCallback && this.successCallback(this.value);
    while(this.successCallback.length) this.successCallback.shift()();
  }
  reject=reason=>{
    // 判断状态不为等待，阻止执行
    if(this.status !== PENDING) return;
    // 更改状态为失败
    this.status=REJECTED;
    // 保存失败的原因
    this.reason=reason;
    // 判断失败回调是否存在，存在=>调用
    // this.failCallback && this.failCallback(this.reason);
    while(this.failCallback.length) this.failCallback.shift()();

  }
  then(successCallback,failCallback){
    successCallback=successCallback?successCallback:value=>value;
    failCallback=failCallback?failCallback:reason=> {throw (reason);}
    let promise2 = new Promise((resolve,reject)=>{
      //判断状态
      if(this.status === FULFILLED){
        setTimeout(() => {
          try{
             let x=successCallback(this.value);
            // 判断x的值是普通值还是promise对象
            // 如果是普通值，直接调用resolve
            // 如果是promise对象，查看promise对象返回的结果
            // 再根据promise对象返回结果，决定调用resolve还是reject
            resolvePromise(promise2,x,resolve,reject);
          }catch(e){
            reject(e);
          }
        }, 0);
      }else if(this.status === REJECTED){
        setTimeout(() => {
          try{
             let x=failCallback(this.reason);
            // 判断x的值是普通值还是promise对象
            // 如果是普通值，直接调用resolve
            // 如果是promise对象，查看promise对象返回的结果
            // 再根据promise对象返回结果，决定调用resolve还是reject
            resolvePromise(promise2,x,resolve,reject);
          }catch(e){
            reject(e);
          }
        }, 0);
      }else{
        //等待
        // 将成功回调和失败回调存储起来
        this.successCallback.push(()=>{
          setTimeout(() => {
            try{
               let x=successCallback(this.value);
              // 判断x的值是普通值还是promise对象
              // 如果是普通值，直接调用resolve
              // 如果是promise对象，查看promise对象返回的结果
              // 再根据promise对象返回结果，决定调用resolve还是reject
              resolvePromise(promise2,x,resolve,reject);
            }catch(e){
              reject(e);
            }
          }, 0);
        });
        this.failCallback.push(()=>{
          setTimeout(() => {
            try{
               let x=failCallback(this.reason);
              // 判断x的值是普通值还是promise对象
              // 如果是普通值，直接调用resolve
              // 如果是promise对象，查看promise对象返回的结果
              // 再根据promise对象返回结果，决定调用resolve还是reject
              resolvePromise(promise2,x,resolve,reject);
            }catch(e){
              reject(e);
            }
          }, 0);
        });
      }
    });
    return promise2
  }
  finally(callback){
    return this.then(value=>{
      return MyPromise.resolve(callback()).then(()=>value);
    }, reason=>{
      return MyPromise.resolve(callback()).then(()=>{throw reason});
    })
  }
  catch(failCallack){
    return this.then(undefined,failCallack)
  }
  static all(array){
    let result=[];
    let index=0;
    return new MyPromise((resolve,reject)=>{
      function addData(key,value){
        result[key]=value;
        index++;
        if(index===array.length){
          resolve(result);
        }
      }
      for(let i=0;i<array.length;i++){
        let current = array[i];
        if(current instanceof MyPromise){
          // promise 对象
          current.then(value=>addData(i,value),reason=>reject(reason))
        }else{
          // 普通值
          addData(i,array[i]);
        }
      }
    })
  }
  static resolve(value){
    if(value instanceof MyPromise) return value;
    return new MyPromise(resolve=>resolve(value))
  }
}
function resolvePromise(promise2,x,resolve,reject){
  if(promise2===x){
    return reject(new TypeError('Chaining cucle detected for promise #<Promise>'))
  }
  if(x instanceof MyPromise){
    // promise 对象
    // x.then(value=>resolve(value),reason=>reject(reason))
    x.then(resolve,reject)
  }else{
    // 普通值
    resolve(x);
  }
}



// let promise = new MyPromise((resolve,reject)=>{
//   setTimeout(() => {
//     resolve("成功");
//   }, 2000);
//   // throw new Error('手写的错误');
//   // resolve("成功");
//   // reject("失败");
// });

function other(){
  return new MyPromise((resolve,reject)=>{
    // resolve("other");
    reject("shdiother");
  })
}
other().then(value=>{
  console.log(value)
}).catch(reason=>{
  console.log(reason)
})
function promise(){
  return new MyPromise((resolve,reject)=>{
    setTimeout(() => {
      resolve("成功");
    }, 2000);
  })
}
// other().finally(()=>{
//   console.log('finally');
//   return promise();
// }).then(value=>{
//   console.log(value)
// },reason=>{
//   console.log(reason)
// })
// let othe=promise.then().then(value=>{
//   console.log(value)
//   // return p1;
// },reason=>{
//   console.log(reason)
// })
// p1.then(value=>{
//   console.log(value)
// },reason=>{
//   console.log(reason.message)
// })